<template>
  <!-- 21.2使用 element-plus 组件库 使用 Dialog 对话框 --- 自定义内容  -->
  <div class="edituser_container">
    <!-- 21.3复制以下代码 -->
    <!-- 21.9修改 dialog 对话框的信息 -->
    <!-- <el-dialog v-model="dialogFormVisible" title="添加用户"> -->
    <!-- 21.33这里的显示隐藏改为父组件传过来的 show,这里会报错： v-model cannot be used on a prop, because local prop bindings are not writable.，因为这里一开始用的是 v-model，但是父组件传进来的数据 prop 的，不可以使用v-model，要在 element-plus 里面看 dialog 对话框组件的属性，model-value / v-model 	是否显示 Dialog，这里改成 :model-value  就好了 -->
    <!-- <el-dialog v-model="show" title="添加用户"> -->
    <!-- 21.34去到 adimi.vue 文件夹，去给添加按钮绑定点击事件 -->
    <!-- <el-dialog :model-value="show" title="添加用户"> -->
    <!-- 17.8绑定关闭的 Dialog 的方法 -->
    <!-- <el-dialog :model-value="show" title="添加用户" @close="IcloseDialogFn"> -->
    <!-- 23.48这里传个布尔值，是否需要重新请求Table数据,这里添加用户的按钮，点击关闭，不需要重新请求Table数据 -->
    <el-dialog :model-value="show" title="添加用户" @close="IcloseDialogFn(false)">
      <!-- 21.22定义的 rules 规则需要在这里使用rules属性 -->
      <!-- <el-form :model="form"> -->
      <el-form :model="form" :rules="rules">
        <!-- 21.23加上 rules 的话，这里每一个都要加上 prop -->
        <!-- <el-form-item label="账号：" label-width="140px"> -->
        <el-form-item label="账号：" label-width="140px" prop="username">
          <el-input v-model="form.username" autocomplete="off" placeholder="请输入账号" />
        </el-form-item>
        <el-form-item label="姓名：" label-width="140px" prop="
        nickName">
          <el-input v-model="form.nickName" autocomplete="off" placeholder="请输入姓名" />
        </el-form-item>
        <el-form-item label="邮箱：" label-width="140px" prop="email">
          <el-input v-model="form.email" autocomplete="off" placeholder="请输入邮箱" />
        </el-form-item>
        <el-form-item label="密码：" label-width="140px" prop="password">
          <!-- 21.24密码要加上 type="password"  -->
          <!-- <el-input v-model="form.password" autocomplete="off" placeholder="请输入密码" type="password" /> -->
          <!-- 23.26这里我们不允许修改密码，组件自带的禁用的属性 disabled，不然这样子就超级管理员可以随意修改密码，会出现安全隐患 -->
          <el-input v-model="form.password" autocomplete="off" placeholder="请输入密码" type="password" :disabled="id != 0" />
        </el-form-item>

        <el-form-item label="备注：" label-width="140px">
          <!-- 21.20这里是文本域，找到 element-plus 里面的 Input 输入框 里面的 文本域，添加 type="textarea" 属性来将 input 元素转换为原生的 textarea 元素，文本域高度可通过 rows 属性控制  -->
          <!-- <el-input v-model="form.note" autocomplete="off" placeholder="请输入备注"/> -->
          <el-input v-model="form.note" autocomplete="off" placeholder="请输入备注" type="textarea" :rows="3" />
        </el-form-item>
        <el-form-item label="是否启用：" label-width="140px">
          <!-- <el-input v-model="form.status" autocomplete="off" /> -->
          <!-- 21.18这里是显示单选 是/否，找到 element-plus 组件库里面的 Radio 单选框 --- 基础用法 -->
          <el-radio-group v-model="form.status" class="ml-4">
            <!-- 21.19我们是通过 0 和 1 去显示是否启用， 1是启用，0是禁用 -->
            <el-radio :label="1" size="large">是</el-radio>
            <el-radio :label="0" size="large">否</el-radio>
          </el-radio-group>
        </el-form-item>

      </el-form>

      <template #footer>
        <span class="dialog-footer">
          <!-- <el-button @click="dialogFormVisible = false">取消</el-button> -->
          <!-- 17.11绑定关闭 Dialog 的方法 -->
          <!-- <el-button @click="IcloseDialogFn">取消</el-button> -->
          <!-- 23.49这里传个布尔值，是否需要重新请求Table数据,这里取消的按钮，点击关闭，不需要重新请求Table数据 -->
          <el-button @click="IcloseDialogFn(false)">取消</el-button>
          <!-- <el-button type="primary" @click="dialogFormVisible = false"> -->

          <!-- 17.12用户点击确定事件的话，需要去到 http 文件夹里面的 api.ts 发送用户注册接口 -->
          <el-button type="primary" @click="submitFn">
            确定
          </el-button>
        </span>
      </template>

    </el-dialog>
  </div>
</template>
<script setup lang='ts'>
import { ref, reactive, toRef, watch } from 'vue';

import { ApiRegisterUser, ApiqueryEditUser, ApiUpdateUserInfo } from '@/http/api'
// @ts-ignore
import { ElMessage, ElMessageBox } from 'element-plus'

// 17.9这里使用 emit 去传递子传父的方法
const emit = defineEmits(['close'])

// 17.10定义关闭 Dialog 的方案
// const IcloseDialogFn = () => {
// 23.44这里因为我们需要传一个布尔值来控制，是否需要重新请求表格数据
const IcloseDialogFn = (isReload: boolean) => {
  // console.log('触发了关闭close');
  // emit('close')
  // 23.45这里需要将布尔值传入
  emit('close', isReload)
  // 19.35这里调用清空表单数据的方法，把右边对象里面的每个键，合并到左边对象 
  Object.assign(form, initForm)
  // 上面这行代码相当于下面这部分代码
  // for (let key in initForm) {
  //     form[key] = initForm[key] // 把每个字段的值设置到右边对象中
  // }
  // 因为下面的代码，其实就是上面的循环一行一行写
  // form.username = initForm.username
  // form.nickName = initForm.nickName
}

// 21.4将方法拿过来
// 21.5去到 views 文件夹里面的 ums 文件夹里面的 admin.vue 里面引入该组件
// 21.8这里设置为 true ,就会一开始默认显示该组件
// const dialogFormVisible = ref(false)

// 21.25这里的显示隐藏，应该由父组件来控制这个 show 的显隐，去到父组件 ums 文件夹 admin.vue
// 21.30隐藏以下代码
// const dialogFormVisible = ref(true)

// 21.31在子组件接收父组件传过来的数据
// defineProps({
//   // 21.32接收 show 数据
//   show: {
//     type: Boolean,
//     default: false
//   }
// })

// 23.8接收父组件传过来的数据
const props = defineProps({
  id: {
    type: Number,
    // 23.9默认值为0
    default: 0
  }
})

// 23.10获取id的ref对象，方便后续操作id的值
const id = toRef(props, 'id')
// 23.11监听id是否发生变化，因为id初始值是为0，只要id发生变化就需要做操作
watch(id, () => {
  // 23.12如果id为0，就退出
  if (id.value === 0) {
    return
  }
  // 23.13如果不为0就向服务器请求数据回来，去到 http 文件夹里面的 api.ts 发送请求
  // 23.16发送请求
  ApiqueryEditUser(id.value).then(res => {
    // 23.17查看请求的结果
    // console.log(res);
    // 23.18请求成功的后端逻辑
    if (res.code === 200) {
      // 23.19获取到当前点击id的用户信息，赋值给表单的数据，把右边对象里面的每个键，合并到左边对象
      // 23.20这个时候点击编辑按钮，就是显示当前的数据
      // 23.21去到 http 文件夹里面的 api.ts 
        (form, res.data)
    }
  })
})

const show = ref(false)

defineExpose({ show })


// 21.10因为这里是绑定 dialog 里面的数据，然后请求接口，所以我们要找到接口文档 /admin/register用户注册 ，这里需要携带的是 {"email": "string","icon": "string","nickName": "string","note": "string","password": "string","username": "string"}，修改为当前需要的数据
// 21.12约束 form 的数据类型，去到 types 文件夹里面的 api.d.ts
// const form = reactive({

// 21.17 约束 form 类型

// 19.32因为用户提交确定按钮之后，需要重新清空数据，所以这里先将一开始定义的默认数据存起来
const initForm = {
  username: '',
  nickName: '',
  email: '',
  password: '',
  note: '',
  status: 1,
  // 23.24添加id，初始值为0
  id: 0
}
// 19.31隐藏以下代码
// const form = reactive<IUserModel>({
//   username: '',
//   nickName: '',
//   email: '',
//   password: '',
//   note: '',
//   // 21.11因为接口没有要求到禁用启用的 status 状态，我们自己加上
//   status: 0
// })

// 19.33这里再定义响应式数据
// const form = reactive<IUserModel>(initForm)
// 19.34这里需要拓展运算符去浅拷贝，不然会修改到原有的数据
// const form = reactive<IUserModel>({ ...initForm })
// 23.25这里约束的类型 IUserListModel 改成这个
const form = reactive<IUserListModel>({ ...initForm })

//@ts-ignore
const verifyPassword = (rule: any, value: string, callback: any) => {
  let reg = /^[0-9a-zA-Z]{6,}$/;
  if (value && !reg.test(value)) {
    return callback(new Error("密码格式不正确"));
  } else {
    callback();
  }
};

// const verifyPassword = (rule: any, value: string, callback: any) => {
//   if (!value) {
//     return callback(new Error('请输入密码'))
//   }
//   if (!/\d/.test(value)) {
//     return callback(new Error('密码中必须包含数字'))
//   }
//   if (!/[a-zA-Z]/.test(value)) {
//     return callback(new Error('密码中必须包含字母'))
//   }
//   if (/\W/.test(value)) {
//     return callback(new Error('密码中包含非法字符'))
//   }
//   callback();
// }



// 21.21需要对用户输入的表单进行验证
const rules = {
  username: [ 
    
    { required: true, trigger: 'blur', message: '请输入账号' },
    { min: 6, max: 20, trigger: 'blur', message: '账号必须在6-20个字符之间' }
  ],
  nickName: [
    { required: true, trigger: 'blur', message: '请输入账号' }
  ],
  email: [
    { required: true, trigger: 'blur', message: '请输入邮箱' },
    { trigger: 'blur', message: '请输入正确的邮箱', pattern: /^\w+[@]\w+[.]\w+/ },
  ],
  password: [
    { required: true, message: "请输入密码", trigger: "blur" },
    {
      validator: verifyPassword,
      message: "密码长度不能少于6位",
      trigger: "blur"
    }
    // { trigger: 'blur', message: '密码必须由数字、字母组成', validator: verifyPassword },
  ],
}

// 确认的按钮点击事件
const submitFn = () => {
  // 17.29先隐藏以下的代码
  // // 17.15在发送请求之前要，验证表单是否已经通过，这个操作在登录的时候做过了，这边可以参考

  // // 17.16发送接口请求,res.data返回的数据需要去到 http 文件夹里面的 api.ts 文件
  // ApiRegisterUser(form).then(res => {
  //   // 17.19如果请求成功
  //   if (res.code === 200) {
  //     // 17.20弹出提示框
  //     ElMessage({
  //       type: 'success',
  //       message: '添加成功'
  //     })
  //     // 17.21隐藏弹出的 Dialog,这里需要用个变量传过去，去到父组件 admin.vue 接收
  //     emit('close', true);
  //   }

  // })

  // 23.27将以下代码抽离出去外面封装起来，因为我们有一些是不一定需要的
  // 17.30用户点击确认的时候再提示，使用 element-plus里面的 Message Box 消息弹出框 --- 确认消息
  // ElMessageBox.confirm('确定要添加新用户吗', '确认操作', {
  //   confirmButtonText: '确定',
  //   cancelButtonText: '取消',
  // }).then(() => {
  //   // 17.31将发送用户注册接口搬到以下
  //   ApiRegisterUser(form).then(res => {
  //     // 17.32请求成功
  //     if (res.code === 200) {
  //       // 17.33弹框提示
  //       // 17.34去到 admin.vue 组件
  //       ElMessage({
  //         type: 'success',
  //         message: '添加成功'
  //       })
  //       // 19.36这里直接调用写好的关闭方法
  //       IcloseDialogFn()
  //     }
  //   })
  // }).catch(() => { })

  // 23.30这里需要进行判断，如果 id 为 0 就是添加用户，调用 addUser 的方法，如果不为 0 ，那么就是点击编辑按钮，修改用户信息的方法
  id.value === 0 ? addUser() : updateUser()
}

// 23.28把 submitFn 里面的代码抽离到这里
const addUser = () => {
  ElMessageBox.confirm('确定要添加新用户吗', '确认操作', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
  }).then(() => {
    ApiRegisterUser(form).then(res => {
      if (res.code === 200) {
        ElMessage({
          type: 'success',
          message: '添加成功'
        })

        // 23.47这里传个布尔值，是否需要重新请求Table数据
        IcloseDialogFn(true)
      }
    })
  }).catch(() => { })
}

// 23.29 修改用户信息的方法 updateUser 
const updateUser = () => {
  // 23.31完善修改指定用户信息，去到 http 文件夹里面的 api.ts 发送接口请求

  // 23.39隐藏以下代码，我们在最外面还要加一层弹框 ElMessageBox
  // 23.35发送请求
  // ApiUpdateUserInfo(form).then(res => {
  //   // 23.36发现该接口返回的数据是：data:1，所以接口返回的数据 data 是数字，去到 http 文件夹里面的 api.ts
  // })

  // 23.40点击编辑按钮，确认修改用户信息的时候会出现的提示框 ElMessageBox，提示是否修改
  ElMessageBox.confirm('此操作将修改当前用户信息', '是否继续', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
  }).then(() => {
    // 23.41在这里发送请求
    ApiUpdateUserInfo(form).then(res => {
      if (res.code === 200) {
        ElMessage({
          type: 'success',
          message: '修改成功'
        })
        // 23.42关闭弹出框
        // IcloseDialogFn()
        // 23.46这里传个布尔值，是否需要重新请求Table数据
        // 23.50这里可以看到请求，编辑完成表格数据，我们传入 true 就会再次触发获取表格新数据
        IcloseDialogFn(true)
      }
    })
  }).catch(() => { })
}



</script>
<style lang="less" scoped></style>